package com.example.docmanagement.controller;

import com.example.docmanagement.dto.request.ChangePasswordRequest;
import com.example.docmanagement.dto.request.ForgotPasswordRequest;
import com.example.docmanagement.dto.request.LoginRequest;
import com.example.docmanagement.dto.request.RegisterRequest;
import com.example.docmanagement.dto.request.ResetPasswordConfirmRequest;
import com.example.docmanagement.dto.response.ApiResponse;
import com.example.docmanagement.dto.response.AuthResponse;
import com.example.docmanagement.dto.response.PasswordResetTokenResponse;
import com.example.docmanagement.service.AuthService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.*;

/**
 * 认证控制器
 * 处理用户登录、注册、Token刷新等认证相关请求
 * 
 * 基础路径：/api/v1/auth
 * 
 * 主要功能：
 * - 用户登录（支持邮箱或用户名登录）
 * - 用户注册（创建新账号）
 * - Token刷新（获取新的访问令牌）
 * - 用户登出
 */
@Tag(name = "认证管理", description = "用户认证相关接口")
@RestController
@RequestMapping("/api/v1/auth")
@RequiredArgsConstructor
public class AuthController {

    private final AuthService authService;

    /**
     * 用户登录接口
     * 
     * 接口路径：POST /api/v1/auth/login
     * 
     * 功能说明：
     * - 支持使用邮箱或用户名登录
     * - 返回JWT访问令牌和刷新令牌
     * - 返回用户基本信息
     * 
     * 请求示例：
     * POST /api/v1/auth/login
     * Content-Type: application/json
     * 
     * {
     * "email": "user@example.com",
     * "password": "password123"
     * }
     * 
     * 响应示例：
     * {
     * "success": true,
     * "data": {
     * "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
     * "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
     * "tokenType": "Bearer",
     * "expiresIn": 86400,
     * "user": {
     * "id": "550e8400-e29b-41d4-a716-446655440000",
     * "email": "user@example.com",
     * "username": "zhangsan",
     * "fullName": "张三",
     * "roleName": "USER"
     * }
     * },
     * "message": "操作成功"
     * }
     *
     * @param request 登录请求对象，包含邮箱/用户名和密码
     * @return 包含JWT Token和用户信息的响应
     */
    @Operation(summary = "用户登录", description = "通过邮箱或用户名登录，返回 JWT Token 和用户基本信息")
    @ApiResponses({
            @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "登录成功", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = AuthResponse.class))),
            @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "请求参数错误"),
            @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "401", description = "用户名或密码错误")
    })
    @PostMapping("/login")
    public ResponseEntity<ApiResponse<AuthResponse>> login(
            @Parameter(description = "登录请求参数", required = true) @Valid @RequestBody LoginRequest request) {
        AuthResponse response = authService.login(request);
        return ResponseEntity.ok(ApiResponse.success(response));
    }

    /**
     * 用户注册接口
     * 
     * 接口路径：POST /api/v1/auth/register
     * 
     * 功能说明：
     * - 创建新用户账号
     * - 验证邮箱和用户名的唯一性
     * - 密码自动加密存储
     * - 注册成功后自动登录，返回JWT令牌
     * 
     * 请求示例：
     * POST /api/v1/auth/register
     * Content-Type: application/json
     * 
     * {
     * "email": "newuser@example.com",
     * "username": "zhangsan",
     * "password": "password123",
     * "fullName": "张三"
     * }
     * 
     * 响应示例：
     * {
     * "success": true,
     * "data": {
     * "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
     * "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
     * "tokenType": "Bearer",
     * "expiresIn": 86400,
     * "user": {
     * "id": "550e8400-e29b-41d4-a716-446655440000",
     * "email": "newuser@example.com",
     * "username": "zhangsan",
     * "fullName": "张三",
     * "roleName": "USER"
     * }
     * },
     * "message": "操作成功"
     * }
     *
     * @param request 注册请求对象，包含邮箱、用户名、密码等信息
     * @return 包含JWT Token和新用户信息的响应
     */
    @Operation(summary = "用户注册", description = "创建新用户账号，注册成功后自动登录并返回 JWT Token")
    @ApiResponses({
            @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "注册成功", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = AuthResponse.class))),
            @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "400", description = "请求参数错误或邮箱/用户名已存在")
    })
    @PostMapping("/register")
    public ResponseEntity<ApiResponse<AuthResponse>> register(
            @Parameter(description = "注册请求参数", required = true) @Valid @RequestBody RegisterRequest request) {
        AuthResponse response = authService.register(request);
        return ResponseEntity.ok(ApiResponse.success(response));
    }

    /**
     * 刷新Token接口
     * 
     * 接口路径：POST /api/v1/auth/refresh
     * 
     * 功能说明：
     * - 使用Refresh Token获取新的Access Token
     * - 用于在Access Token过期后保持用户登录状态
     * - 建议在Access Token即将过期时主动调用此接口
     * 
     * 请求示例：
     * POST
     * /api/v1/auth/refresh?refreshToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
     * 
     * 响应示例：
     * {
     * "success": true,
     * "data": {
     * "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
     * "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
     * "tokenType": "Bearer",
     * "expiresIn": 86400,
     * "user": {
     * "id": "550e8400-e29b-41d4-a716-446655440000",
     * "email": "user@example.com",
     * "username": "zhangsan",
     * "fullName": "张三",
     * "roleName": "USER"
     * }
     * },
     * "message": "操作成功"
     * }
     *
     * @param refreshToken 刷新令牌，从登录或注册时获得
     * @return 包含新的Access Token的响应
     */
    @Operation(summary = "刷新Token", description = "使用 Refresh Token 获取新的 Access Token，延长用户登录状态")
    @ApiResponses({
            @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "刷新成功", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = AuthResponse.class))),
            @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "401", description = "Refresh Token无效或已过期")
    })
    @PostMapping("/refresh")
    public ResponseEntity<ApiResponse<AuthResponse>> refreshToken(
            @Parameter(description = "刷新令牌", required = true, example = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...") @RequestParam String refreshToken) {
        AuthResponse response = authService.refreshToken(refreshToken);
        return ResponseEntity.ok(ApiResponse.success(response));
    }

    /**
     * 忘记密码，申请重置令牌
     */
    @Operation(summary = "申请密码重置", description = "提交注册邮箱，系统生成重置令牌并返回（生产环境应通过邮件发送）")
    @PostMapping("/password/forgot")
    public ResponseEntity<ApiResponse<PasswordResetTokenResponse>> forgotPassword(
            @Parameter(description = "忘记密码请求参数", required = true) @Valid @RequestBody ForgotPasswordRequest request) {
        PasswordResetTokenResponse response = authService.requestPasswordReset(request);
        return ResponseEntity.ok(ApiResponse.success(response, "如果邮箱存在，重置指引已发送。"));
    }

    /**
     * 使用令牌重置密码
     */
    @Operation(summary = "重置密码", description = "携带重置令牌与新密码，完成密码重置")
    @PostMapping("/password/reset")
    public ResponseEntity<ApiResponse<Void>> resetPassword(
            @Parameter(description = "重置密码请求参数", required = true) @Valid @RequestBody ResetPasswordConfirmRequest request) {
        authService.resetPassword(request);
        return ResponseEntity.ok(ApiResponse.success(null, "密码重置成功"));
    }

    /**
     * 登录状态下修改密码
     */
    @Operation(summary = "修改密码", description = "登录状态下修改当前账号密码")
    @PreAuthorize("isAuthenticated()")
    @PostMapping("/password/change")
    public ResponseEntity<ApiResponse<Void>> changePassword(
            @AuthenticationPrincipal UserDetails userDetails,
            @Parameter(description = "修改密码请求参数", required = true) @Valid @RequestBody ChangePasswordRequest request) {
        if (userDetails == null) {
            throw new BadCredentialsException("未登录或登录状态已失效");
        }
        String username = userDetails.getUsername();
        authService.changePassword(username, request);
        return ResponseEntity.ok(ApiResponse.success(null, "密码修改成功"));
    }

    /**
     * 用户登出接口
     * 
     * 接口路径：POST /api/v1/auth/logout
     * 
     * 功能说明：
     * - 退出当前登录状态
     * - 由于使用JWT无状态认证，服务端不存储Token
     * - 客户端需要主动删除本地存储的Token
     * - 如需服务端强制登出，可以实现Token黑名单机制
     * 
     * 请求示例：
     * POST /api/v1/auth/logout
     * Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
     * 
     * 响应示例：
     * {
     * "success": true,
     * "data": null,
     * "message": "登出成功"
     * }
     *
     * @return 操作成功响应
     */
    @Operation(summary = "用户登出", description = "退出登录，客户端需要删除本地存储的 Token")
    @ApiResponses({
            @io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "登出成功")
    })
    @PostMapping("/logout")
    public ResponseEntity<ApiResponse<Void>> logout() {
        // JWT 是无状态的，客户端删除 Token 即可
        // 如果需要服务端管理，可以实现 Token 黑名单
        return ResponseEntity.ok(ApiResponse.success(null, "登出成功"));
    }
}
